/**
 * Created by Weizehua on 2017/1/19.
 */
import {Newable, Injector} from "ts.di";
import {Metadata} from "../../Utils/Metadata/Metadata";
import {HandlerType, FormalHandlerResponse} from "./Types";

export class Caller {
    register<T>(ctor: Newable<T>, val: T) {
        // logger.debug(`registered ${ctor.name}:${val}`)
        ctor[this.sessionSymbol] = val;
        this.registeredClass.push(ctor);
    }

    unRegisterAll() {
        for (let ctor of this.registeredClass) {
            delete ctor[this.sessionSymbol];
        }
    }

    async call(func: HandlerType): Promise<FormalHandlerResponse> {
        // logger.debug(`func : ${func}`);
        let argTypes = Metadata.paramTypes(func);
        // prepare arguments it needs
        let args = [];
        for (let i = 0; i < argTypes.length; i++) {
            let ctor = argTypes[i];
            if (!ctor.hasOwnProperty(this.sessionSymbol)) {
                throw new Error(`${argTypes[i].name} is not registered in Caller!`);
            }
            args.push(ctor[this.sessionSymbol]);
        }
        // logger.debug(`args(${args.length}):`, ...args);
        this.lastCall = func;
        return func.apply(Injector.get(Metadata.ctor<any>(func)), args);
    }

    lastCall: Function;
    private sessionSymbol = Symbol("Caller.sessionSymbol");
    private registeredClass = [];
}
